home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / src.arc / PKTDRVR.C < prev    next >
C/C++ Source or Header  |  1989-08-19  |  10KB  |  398 lines

  1. /* Driver for FTP Software's packet driver interface */
  2. #include <stdio.h>
  3. #include <dos.h>
  4. #include "global.h"
  5. #include "proc.h"
  6. #include "mbuf.h"
  7. #include "enet.h"
  8. #include "ax25.h"
  9. #include "slip.h"
  10. #include "kiss.h"
  11. #include "iface.h"
  12. #include "ec.h"
  13. #include "timer.h"
  14. #include "arp.h"
  15. #include "trace.h"
  16. #include "pktdrvr.h"
  17. #include "config.h"
  18.  
  19. static int access_type __ARGS((int intno,int if_class,int if_type,int if_number,
  20.     char *type,unsigned typelen,INTERRUPT (*receiver) __ARGS((void)) ));
  21. #ifdef    notdef
  22. static int driver_info __ARGS((int intno,int handle,int *version,
  23.     int *class,int *type,int *number,int *basic));
  24. #endif
  25. static int release_type __ARGS((int intno,int handle));
  26. static int get_address __ARGS((int intno,int handle,char *buf,int len));
  27. static int pk_raw __ARGS((struct iface *iface,struct mbuf *bp));
  28. static int pk_stop __ARGS((struct iface *iface));
  29. static int send_pkt __ARGS((int intno,char *buffer,unsigned length));
  30.  
  31.  
  32. static INTERRUPT (*Pkvec[])() = { pkvec0,pkvec1,pkvec2 };
  33. static struct pktdrvr Pktdrvr[PK_MAX];
  34. static unsigned int Npk;
  35. static int Derr;
  36.  
  37. /* Send raw packet (caller provides header) */
  38. static int
  39. pk_raw(iface,bp)
  40. struct iface *iface;    /* Pointer to interface control block */
  41. struct mbuf *bp;    /* Data field */
  42. {
  43.     register struct pktdrvr *pp;
  44.     int16 size;
  45.     struct mbuf *bp1;
  46.  
  47.     pp = &Pktdrvr[iface->dev];
  48.     size = len_mbuf(bp);
  49.  
  50.     switch(pp->class){
  51.     case CL_ETHERNET:
  52.         dump(iface,IF_TRACE_OUT,TYPE_ETHER,bp);
  53.         if(size < 60)
  54.             size = 60;
  55.         break;
  56.     case CL_SERIAL_LINE:
  57.         dump(iface,IF_TRACE_OUT,TYPE_IP,bp);
  58.         break;
  59.     case CL_AX25:
  60.         dump(iface,IF_TRACE_OUT,TYPE_AX25,bp);
  61.         break;
  62.     case CL_KISS:
  63.         dump(iface,IF_TRACE_OUT,TYPE_AX25,bp);
  64.         /* This *really* shouldn't be done here, but it was the
  65.          * easiest way. Put the type field for KISS TNC on front.
  66.          */
  67.         if((bp1 = pushdown(bp,1)) == NULLBUF){
  68.             free_p(bp);
  69.             return -1;
  70.         }
  71.         bp = bp1;
  72.         bp->data[0] = KISS_DATA;
  73.         break;
  74.     }
  75.     if(bp->next != NULLBUF){
  76.         /* Copy to contiguous buffer, since driver can't handle mbufs */
  77.         bp1 = copy_p(bp,size);
  78.         free_p(bp);
  79.         bp = bp1;
  80.         if(bp == NULLBUF)
  81.             return -1;
  82.     } else
  83.         bp->cnt = size;    /* Make sure packet size is big enough */
  84.  
  85.     send_pkt(pp->intno,bp->data,bp->cnt);
  86.     free_p(bp);
  87.     return 0;
  88. }
  89.  
  90. /* Packet driver receive routine. Called from an assembler hook that pushes
  91.  * the caller's registers on the stack so we can access and modify them.
  92.  * This is a rare example of call-by-location in C.
  93.  */
  94. void
  95. pkint(dev,di,si,bp,dx,cx,bx,ax,ds,es)
  96. unsigned short dev,di,si,bp,dx,cx,bx,ax,ds,es;
  97. {
  98.     register struct pktdrvr *pp;
  99.     struct phdr *phdr;
  100.  
  101.     if(dev >= Npk)
  102.         return;    /* Unknown packet */
  103.     pp = &Pktdrvr[dev];
  104.  
  105.     switch(ax){
  106.     case 0:    /* Space allocate call */
  107.         if((pp->buffer = alloc_mbuf(cx+sizeof(struct phdr))) != NULLBUF){
  108.             es = FP_SEG(pp->buffer->data);
  109.             di = FP_OFF(pp->buffer->data+sizeof(struct phdr));
  110.             pp->buffer->cnt = cx + sizeof(struct phdr);
  111.             phdr = (struct phdr *)pp->buffer->data;
  112.             phdr->iface = pp->iface;
  113.             switch(pp->class){
  114.             case CL_ETHERNET:
  115.                 phdr->type = TYPE_ETHER;
  116.                 break;
  117.             case CL_SERIAL_LINE:
  118.                 phdr->type = TYPE_IP;
  119.                 break;
  120.             case CL_AX25:
  121.                 phdr->type = TYPE_AX25;
  122.                 break;
  123.             case CL_KISS:
  124.                 phdr->type = TYPE_KISS;
  125.                 break;
  126.             }
  127.         } else {
  128.             es = di = 0;
  129.         }
  130.         break;
  131.     case 1:    /* Packet complete call */
  132.         enqueue(&Hopper,pp->buffer);
  133.         pp->buffer = NULLBUF;
  134.         break;
  135.     default:
  136.         break;
  137.     }
  138. }
  139.  
  140. /* Shut down the packet interface */
  141. static int
  142. pk_stop(iface)
  143. struct iface *iface;
  144. {
  145.     struct pktdrvr *pp;
  146.  
  147.     pp = &Pktdrvr[iface->dev];
  148.     /* Call driver's release_type() entry */
  149.     if(release_type(pp->intno,pp->handle1) == -1)
  150.         printf("%s: release_type error code %u\n",iface->name,Derr);
  151.  
  152.     if(pp->class == CL_ETHERNET)
  153.         release_type(pp->intno,pp->handle2);
  154.     return 0;
  155. }
  156. /* Attach a packet driver to the system
  157.  * argv[0]: hardware type, must be "packet"
  158.  * argv[1]: software interrupt vector, e.g., x7e
  159.  * argv[2]: interface label, e.g., "trw0"
  160.  * argv[3]: maximum number of packets allowed on transmit queue, e.g., "5"
  161.  * argv[4]: maximum transmission unit, bytes, e.g., "1500"
  162.  */
  163. int
  164. pk_attach(argc,argv,p)
  165. int argc;
  166. char *argv[];
  167. void *p;
  168. {
  169.     register struct iface *if_pk;
  170.     int class;
  171.     unsigned int intno;
  172.     static char iptype[] = {IP_TYPE >> 8,IP_TYPE};
  173.     static char arptype[] = {ARP_TYPE >> 8,ARP_TYPE};
  174.     long drvvec;
  175.     char sig[8];    /* Copy of driver signature "PKT DRVR" */
  176.     register struct pktdrvr *pp;
  177.  
  178.     if(Npk >= PK_MAX){
  179.         printf("Too many packet drivers\n");
  180.         return -1;
  181.     }
  182.     if(if_lookup(argv[2]) != NULLIF){
  183.         printf("Interface %s already exists\n",argv[2]);
  184.         return -1;
  185.     }
  186.  
  187.     intno = htoi(argv[1]);
  188.     /* Verify that there's really a packet driver there, so we don't
  189.      * go off into the ozone (if there's any left)
  190.      */
  191.     drvvec = (long)getvect(intno);
  192.     movblock(FP_OFF(drvvec)+3, FP_SEG(drvvec),
  193.         FP_OFF(sig),FP_SEG(sig),strlen(PKT_SIG));
  194.     if(strncmp(sig,PKT_SIG,strlen(PKT_SIG)) != 0){
  195.         printf("No packet driver loaded at int 0x%x\n",intno);
  196.         return -1;
  197.     }
  198.     if((if_pk = (struct iface *)calloc(1,sizeof(struct iface))) == NULLIF
  199.      ||(if_pk->name = strdup(argv[2])) == NULLCHAR){
  200.         free((char *)if_pk);
  201.         printf("pk_attach: no memory!\n");
  202.         return -1;
  203.     }
  204.     pp = &Pktdrvr[Npk];
  205.     if_pk->mtu = atoi(argv[4]);
  206.     if_pk->dev = Npk++;
  207.     if_pk->raw = pk_raw;
  208.     if_pk->stop = pk_stop;
  209.     pp->intno = intno;
  210.     pp->iface = if_pk;
  211.  
  212.     /* Find out by exhaustive search what class this driver is (ugh) */
  213.     for(class=0;class<9;class++){
  214.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  215.             Pkvec[if_pk->dev]);
  216.         if(pp->handle1 != -1 || Derr == TYPE_INUSE)
  217.             break;
  218.     }
  219.     /* Now that we know, release it and do it all over again with the
  220.      * right type fields
  221.      */
  222.     if(pp->handle1 != -1)
  223.         release_type(intno,pp->handle1);
  224.     switch(class){
  225.     case CL_ETHERNET:
  226.         pp->handle1 = access_type(intno,class,ANYTYPE,0,iptype,2,
  227.             Pkvec[if_pk->dev]);
  228.         pp->handle2 = access_type(intno,class,ANYTYPE,0,arptype,2,
  229.             Pkvec[if_pk->dev]);            
  230.         if_pk->send = enet_send;
  231.         if_pk->output = enet_output;
  232.         /* Get hardware Ethernet address from driver */
  233.         if((if_pk->hwaddr = malloc(EADDR_LEN)) == NULLCHAR){
  234.             free(if_pk->name);
  235.             free((char *)if_pk);
  236.             printf("pk_attach: no memory!\n");
  237.             return -1;
  238.         }
  239.         get_address(intno,pp->handle1,if_pk->hwaddr,EADDR_LEN);
  240.         arp_init(ARP_ETHER,EADDR_LEN,IP_TYPE,ARP_TYPE,1,Ether_bdcst,pether,gether);
  241.         break;
  242. #ifdef    SLIP
  243.     case CL_SERIAL_LINE:
  244.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  245.          Pkvec[if_pk->dev]);
  246.         if_pk->send = slip_send;
  247.         break;
  248. #endif
  249. #ifdef    KISS
  250.     case CL_KISS:    /* Note that the raw routine puts on the command */
  251.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  252.          Pkvec[if_pk->dev]);
  253.         if_pk->send = ax_send;
  254.         if_pk->output = ax_output;
  255.         break;
  256. #endif
  257. #ifdef    AX25
  258.     case CL_AX25:
  259.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,
  260.          Pkvec[if_pk->dev]);
  261.         if_pk->send = ax_send;
  262.         if_pk->output = ax_output;
  263.         break;
  264. #endif
  265.     default:
  266.         printf("Packet driver has unsupported class %u\n",class);
  267.         free(if_pk->name);
  268.         free((char *)if_pk);
  269.         Npk--;
  270.         return -1;
  271.     }
  272.     pp->class = class;
  273.     if_pk->next = Ifaces;
  274.     Ifaces = if_pk;
  275.  
  276.     return 0;
  277. }
  278. static int
  279. access_type(intno,if_class,if_type,if_number,type,typelen,receiver)
  280. int intno;
  281. int if_class;
  282. int if_type;
  283. int if_number;
  284. char *type;
  285. unsigned typelen;
  286. INTERRUPT (*receiver)();
  287. {
  288.     union REGS regs;
  289.     struct SREGS sregs;
  290.  
  291.     segread(&sregs);
  292.     regs.h.dl = if_number;        /* Number */
  293.     sregs.ds = FP_SEG(type);    /* Packet type template */
  294.     regs.x.si = FP_OFF(type);
  295.     regs.x.cx = typelen;        /* Length of type */
  296.     sregs.es = FP_SEG(receiver);    /* Address of receive handler */
  297.     regs.x.di = FP_OFF(receiver);
  298.     regs.x.bx = if_type;        /* Type */
  299.     regs.h.ah = ACCESS_TYPE;    /* Access_type() function */
  300.     regs.h.al = if_class;        /* Class */
  301.     int86x(intno,®s,®s,&sregs);
  302.     if(regs.x.cflag){
  303.         Derr = regs.h.dh;
  304.         return -1;
  305.     } else
  306.         return regs.x.ax;
  307. }
  308. static int
  309. release_type(intno,handle)
  310. int intno;
  311. int handle;
  312. {
  313.     union REGS regs;
  314.  
  315.     regs.x.bx = handle;
  316.     regs.h.ah = RELEASE_TYPE;
  317.     int86(intno,®s,®s);
  318.     if(regs.x.cflag){
  319.         Derr = regs.h.dh;
  320.         return -1;
  321.     } else
  322.         return 0;
  323. }
  324. static int
  325. send_pkt(intno,buffer,length)
  326. int intno;
  327. char *buffer;
  328. unsigned length;
  329. {
  330.     union REGS regs;
  331.     struct SREGS sregs;
  332.  
  333.     segread(&sregs);
  334.     sregs.ds = FP_SEG(buffer);
  335.     regs.x.si = FP_OFF(buffer);
  336.     regs.x.cx = length;
  337.     regs.h.ah = SEND_PKT;
  338.     int86x(intno,®s,®s,&sregs);
  339.     if(regs.x.cflag){
  340.         Derr = regs.h.dh;
  341.         return -1;
  342.     } else
  343.         return 0;
  344. }
  345. #ifdef    notdef
  346. static int
  347. driver_info(intno,handle,version,class,type,number,basic)
  348. int intno;
  349. int handle;
  350. int *version,*class,*type,*number,*basic;
  351. {
  352.     union REGS regs;
  353.  
  354.     regs.x.bx = handle;
  355.     regs.h.ah = DRIVER_INFO;
  356.     regs.h.al = 0xff;
  357.     int86(intno,®s,®s);
  358.     if(regs.x.cflag){
  359.         Derr = regs.h.dh;
  360.         return -1;
  361.     }
  362.     if(version != NULL)
  363.         *version = regs.x.bx;
  364.     if(class != NULL)
  365.         *class = regs.h.ch;
  366.     if(type != NULL)
  367.         *type = regs.x.dx;
  368.     if(number != NULL)
  369.         *number = regs.h.cl;
  370.     if(basic != NULL)
  371.         *basic = regs.h.al;
  372.     return 0;
  373. }
  374. #endif
  375. static int
  376. get_address(intno,handle,buf,len)
  377. int intno;
  378. int handle;
  379. char *buf;
  380. int len;
  381. {
  382.     union REGS regs;
  383.     struct SREGS sregs;
  384.  
  385.     segread(&sregs);
  386.     sregs.es = FP_SEG(buf);
  387.     regs.x.di = FP_OFF(buf);
  388.     regs.x.cx = len;
  389.     regs.x.bx = handle;
  390.     regs.h.ah = GET_ADDRESS;
  391.     int86x(intno,®s,®s,&sregs);
  392.     if(regs.x.cflag){
  393.         Derr = regs.h.dh;
  394.         return -1;
  395.     }
  396.     return 0;
  397. }
  398.